/*
    代码有些地方不是很合理，不过由于时间比较赶，结果是正确的也就没有再做调整
    后期建议根据业务重新开发，谢谢
    write by lei.jiangl
*/
var https = require('https');
// var sqlite3 = require('sqlite3').verbose();
// var querystring = require('querystring');
var ET = require('elementtree');
// var db = new sqlite3.Database('/Users/jiangleivos/alibaba-work/DB/db');
// var $ = require('jquery');
var fs = require('fs');
// var idx = 1;

var timeNow = new Date();
// var tableName = 'test_Id';
// var arg = process.argv[2] || '01'
// var offStep = 2500;
// var tableName = 'keyword_' + arg;
// var tableRstName = 'keyword_rst_' + arg;
// var step = parseInt(parseFloat(arg) / 10 * 100000) //700000
//var workSpace = '/Users/jiangleivos/alibaba-work'
var workSpace = '/home/pts/alibaba-work'
var path = workSpace + '/report/report/keywordEstimate/';
var rstPath = workSpace + '/report/report/targetEstimateResult/';
var arg1 = process.argv[2] || 0;
var arg2 = process.argv[3] || 0;
var arg3 = process.argv[4] || 1;
// var step = 1.0 * 1000000;
// ET.register_namespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/');
// ET.register_namespace('v201', 'https://adwords.google.com/api/adwords/cm/v201209');
// ET.register_namespace('v20', 'https://adwords.google.com/api/adwords/o/v201209');
var SOAP = {
    'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
    'ns_xsd': 'http://www.w3.org/1999/XMLSchema',
    'ns_xsi': 'http://www.w3.org/2001/XMLSchema-instance',
    'ns_soapenc': 'http://schemas.xmlsoap.org/soap/encoding/',
    'v201': 'https://adwords.google.com/api/adwords/cm/v201209',
    'v20': 'https://adwords.google.com/api/adwords/o/v201209'
};
// var startIndex = 0;
// var startIndex = 932501;
// var startIndex = 930001;
// var startIndex = 1665001;   
// var startIndex = 1937501;
// var startIndex = 2540001;

function getToken(callback) {
    // console.log('-----------------------------------------------------getToken');
    logTime('getToken start');
    var qstr = querystring.stringify({
        Email: 'ptapitest@gmail.com',
        Passwd: 'aA123456',
        accountType: 'GOOGLE',
        source: 'adwords-tutorial',
        service: 'adwords'
    });
    // console.log(qstr);
    var sconf = {
        host: 'www.google.com',
        // host:'74.125.128.147',
        path: '/accounts/ClientLogin' + '?' + qstr,
        method: 'GET',
        headers: {}
    };
    var req = https.request(sconf, function(res) {
        // console.log(res);
        res.on('data', function(data) {
            var t = data.toString().split('\n')[2];
            var token = t.split('Auth=')[1];
            logTime('getToken end');
            callback(token);
        });

    })
    req.end();
}

function updateDB(rows, data, callback) {
    // console.log('-----------------------------------------------------updateDB');
    logTime('updateDB start');
    // console.log(data.toString());
    var xml = ET.XML(data.toString());
    var keywordEstimateRequests = xml.findall('.//keywordEstimates');
    // var sqlNew = 'insert into ' + tableRstName + ' (id,min_avgCpc,min_avgPos,min_clickPerDay,min_totalCost,max_avgCpc,max_avgPos,max_clickPerDay,max_totalCost,keyword)  values (?,?,?,?,?,?,?,?,?,?)';
    var sqlNew = 'insert into ' + tableRstName + ' (min_avgCpc,min_avgPos,min_clickPerDay,min_totalCost,max_avgCpc,max_avgPos,max_clickPerDay,max_totalCost,keyword,keyword_rowid)  values ';
    // var sqlStmt = db.prepare(sqlNew);
    var s = '';
    // console.log(toXMLString.call(xml));
    // console.log(keywordEstimateRequests);
    db.serialize(function() {
        // console.log(rows.length,keywordEstimateRequests.length);
        // logTime(rows.length, keywordEstimateRequests.length);
        for (var i in keywordEstimateRequests) {
            var krqst = keywordEstimateRequests[i];
            var min = krqst.find('.//min');
            var minAverageCpc = min.find('.//averageCpc').find('.//ns2:microAmount').text;
            var minAveragePosition = min.find('.//averagePosition').text;
            var minClicksPerDay = min.find('.//clicksPerDay').text;
            var minTotalCost = min.find('.//totalCost').find('.//ns2:microAmount').text;

            var max = krqst.find('.//max');
            var maxAverageCpc = min.find('.//averageCpc').find('.//ns2:microAmount').text;
            var maxAveragePosition = min.find('.//averagePosition').text;
            var maxClicksPerDay = min.find('.//clicksPerDay').text;
            var maxTotalCost = min.find('.//totalCost').find('.//ns2:microAmount').text;
            var keyword = rows[i].keyword;
            // keyword = escape(keyword);
            // console.log(keyword);
            // console.log(rows[i]);
            if (s === '') {
                s = 'begin; ' + sqlNew + '(' + minAverageCpc + ',' + minAveragePosition + ',' + minClicksPerDay + ',' + minTotalCost + ',' + maxAverageCpc + ',' + maxAveragePosition + ',' + maxClicksPerDay + ',' + maxTotalCost + ',' + '"' + keyword + '"' + ',' + rows[i].rowid + ');';
            } else {
                s = s + sqlNew + '(' + minAverageCpc + ',' + minAveragePosition + ',' + minClicksPerDay + ',' + minTotalCost + ',' + maxAverageCpc + ',' + maxAveragePosition + ',' + maxClicksPerDay + ',' + maxTotalCost + ',' + '"' + keyword + '"' + ',' + rows[i].rowid + ');';
            }
        }
        s = s + 'commit;';
        // console.log(s);
        db.exec(s, function(err) {
            if (!err) {
                logTime('updateDB end');
                // console.log(s)
                callback(err);
            } else {
                logTime('updateDB end');
                // console.log(s)
                console.log(err, s);
            }
        });
    });
}


function dbQuery(xml, callback) {
    // console.log('-----------------------------------------------------dbQuery');
    logTime('dbQuery start');
    db.serialize(function() {
        // var sql = 'select * from ' + tableName + ' as a  where a.id>=? and a.id<?';
        // var up = 'update ' + tableName + ' set isDone = 1 where id>=? and id<?';
        var sql = 'select keyword,isDone,rowId from ' + tableName + ' where isDone==0 order by rowid limit ' + offStep;
        // logTime(sql);
        var up = 'update ' + tableName + ' set isDone = 1 where rowid>=? and rowid<=?';
        var stmt = db.prepare(sql);
        var stmtUp = db.prepare(up);
        var length = offStep;

        function fn() {
            logTime('fn start startIndex ');
            // var range = [i, i + length];
            stmt.all(function(err, rows) {
                if (rows.length == length) {
                    var range = [rows[0].rowid, rows[rows.length - 1].rowid];
                    logTime('fn end startIndex ' + range)
                    callback(xml, rows, function(xml) {
                        sendSOAP(xml, function(data) {
                            updateDB(rows, data, function(err) {
                                // console.log('==============',i);
                                if (!err) {
                                    logTime('update table id start');
                                    // console.log('range',range);
                                    stmtUp.run(range, function() {
                                        setTimeout(fn, 10000)
                                        // fn();
                                        logTime('update table id end');
                                    });
                                }

                            });
                        });
                    });
                    // stmtUp.run(range);
                } else if (rows.length != 0) {
                    var range = [rows[0].rowid, rows[rows.length - 1].rowid];
                    logTime('fn end startIndex ' + range);
                    logTime('dbQuery end');
                    callback(xml, rows, function(xml) {
                        sendSOAP(xml, function(data) {
                            updateDB(rows, data, function(err) {
                                if (!err) {
                                    logTime('update table id start');

                                    // console.log(rows);
                                    stmtUp.run(range, function() {
                                        logTime('update table id end');
                                    });
                                }
                            });
                        });
                    });
                }
            });
        }
        fn();
    });
}

function sendSOAP(xml, callback) {
    // console.log('-----------------------------------------------------sendSOAP');
    logTime('sendSOAP start');
    var soapStr = toXMLString.call(xml);
    // console.log('+++++++++++++++++++++++++++++++\n', soapStr);
    var conf = {
        host: 'adwords.google.com',
        // host:'74.125.128.51',
        method: 'POST',
        header: {
            // 'Accept-Encoding': 'gzip,deflate',
            'Content-Type': 'text/xml;charset=UTF-8',
            'Content-Length': soapStr.length
        },
        path: '/api/adwords/o/v201209/TrafficEstimatorService?wsdl'
    }
    var req = https.request(conf, function(res) {
        var dataStr = '';
        logTime('res.statusCode=' + res.statusCode);
        // if(res.statusCode === 500) {
        //     console.log(res);
        // }
        // console.log('===============================', res.statusCode);
        res.on('end', function() {
            // console.log(dataStr);
            logTime('sendSOAP end');
            if (res.statusCode === 500) {
                console.log(soapStr);
                console.log(dataStr);
            } else {
                callback(dataStr);
            }

        })
        var count = 0;
        res.on('data', function(data) {
            dataStr += data.toString();

            //console.log('<><><><><><><><><><><><><><><><>',count++);
            //console.log(data.toString());
            // callback(data);
        });

    });
    // console.log('+++++++++++++++++++++++++++++++\n',soapStr)
    req.write(soapStr);
    req.end();
}

function getGoogleData(xml, keywordMap) {
    // console.log('-----------------------------------------------------createXML');
    logTime('getGoogleData start');
    // console.log(xml);
    // var keywordEstimate = xml.find('.//v20:keywordEstimateRequests');
    // var keywordEstimate = ET.Element('v20:keywordEstimateRequests');

    // console.log(adGroupEstimateRequests);
    // console.log(keywordEstimate);
    var keyArr = [];
    for (var k in keywordMap) {
        keyArr.push(k);
    }

    function _getGoolgeData(kIndex, keywordIdx, callback) {
        var step = 2500;
        var key = keyArr[kIndex];
        // keywordIdx=keywordIdx>keywordMap[key].length-1?keywordMap[key].length-1:keywordIdx
        var keyword = keywordMap[key][keywordIdx];
        var adGroupEstimateRequests = xml.find('.//v20:adGroupEstimateRequests');
        adGroupEstimateRequests.clear();
        logTime(kIndex + '  ' + keywordIdx + '  ' + key + '   start');
        //去重
        var discArr = [],
            discMap = {};
        //一次请求2500个词
        // console.log(keywordMap[key].length,keywordIdx);
        if (keywordMap[key].length - 1 - keywordIdx <= step) {
            step = keywordMap[key].length - 1 - keywordIdx;
        }
        // console.log(step);
        // console.log('step=',step);
        var i = 0;
        do {
            var discKeyword = keywordMap[key][keywordIdx + i];
            discMap[discKeyword] = '';
        } while (++i < step);
        for (var k in discMap) {
            discArr.push(k);
        }
        // console.log(discArr);
        // return;
        discArr.forEach(function(keywordText) {
            // var keywordText = keyword;
            var keywordEstimate = ET.Element('{' + SOAP['v20'] + '}keywordEstimateRequests');
            var keyword = ET.SubElement(keywordEstimate, '{' + SOAP['v20'] + '}keyword');
            var text = ET.SubElement(keyword, '{' + SOAP['v201'] + '}text');
            // text.text = escape(keywordText);
            text.text = unescape(keywordText);
            // console.log(text.text);
            var matchType = ET.SubElement(keyword, '{' + SOAP['v201'] + '}matchType');
            matchType.text = 'EXACT'
            var maxCpc = ET.SubElement(keywordEstimate, '{' + SOAP['v20'] + '}maxCpc');
            var microAmount = ET.SubElement(maxCpc, '{' + SOAP['v201'] + '}microAmount');
            microAmount.text = parseFloat(arg3)*1000000;
            adGroupEstimateRequests.append(keywordEstimate);
            // console.log(keywordText);
        });
        // return;
        sendSOAP(xml, function(xmlStr) { //发送soap请求
            var x = ET.XML(xmlStr);
            var keywordEstimateRequests = x.findall('.//keywordEstimates');
            var kArr = [];
            // console.log(toXMLString.call(xml))//查看请求;
            // console.log(xmlStr)//查看返回结果;
            // return;
            var idx = 0;
            keywordEstimateRequests.forEach(function(krqst) {
                var min = krqst.find('.//min');
                var minAverageCpc = min.find('.//averageCpc').find('.//ns2:microAmount').text;
                var minAveragePosition = min.find('.//averagePosition').text;
                var minClicksPerDay = min.find('.//clicksPerDay').text;
                var minTotalCost = min.find('.//totalCost').find('.//ns2:microAmount').text;
                var max = krqst.find('.//max');
                var maxAverageCpc = min.find('.//averageCpc').find('.//ns2:microAmount').text;
                var maxAveragePosition = min.find('.//averagePosition').text;
                var maxClicksPerDay = min.find('.//clicksPerDay').text;
                var maxTotalCost = min.find('.//totalCost').find('.//ns2:microAmount').text;
                var keyword = discArr[idx];
                // console.log(xmlStr);
                kArr.push([keyword, minAverageCpc, minAveragePosition, minClicksPerDay, minTotalCost, maxAverageCpc, maxAveragePosition, maxClicksPerDay, maxTotalCost]);
                idx++;
            })

            // console.log(keywordArr.length,valueArr.length);
            writeFile(key, kArr); //按照业务逻辑写文件
            logTime(kIndex + '  ' + keywordIdx + '  ' + key + '   end');
            //console.log(keywordIdx )
            // return;
            if (keywordIdx < keywordMap[key].length - 1) {
                // keywordIdx ++;
                keywordIdx += step;
                setTimeout(function() {
                    callback(kIndex, keywordIdx, _getGoolgeData);
                    logTime('getGoogleData end');
                }, 1000)
            } else {
                keywordIdx = 0;
                if (kIndex < keyArr.length - 1) {
                    kIndex++;
                    setTimeout(function() {
                        // body...
                        callback(kIndex, keywordIdx, _getGoolgeData);
                    }, 1000)
                }
            }

        });
    }
    _getGoolgeData(parseInt(arg1), parseInt(arg2), _getGoolgeData);
}

function writeFile(fileName, keywordArr) {
    var _path = rstPath + fileName.split('.')[0] + '_targetEstimate.txt';
    var str = '';
    keywordArr.forEach(function(kArr) {
        str += kArr.join(',') + '\r\n'
    })
    // for (var i = 0; i < keywordArr.length; i++) {
    //     // if(checkKeyword(keywordArr[i],valueArr[i])){
    //     str += keywordArr[i] + ',' + valueArr[i] + ',' + cmptArr[i] + '\r\n';
    //     // }
    // }
    fs.appendFileSync(_path, str);
}

function getKeywordMap(path) {
    var fileArr = [],
        keywordMap = {};
    var files = fs.readdirSync(path);
    files.forEach(function(name) {
        if (name.split('.')[0] !== '') {
            fileArr.push(name);
        }
    })

    fileArr.forEach(function(fileName) { //遍历读取文件夹下所有文件
        var data = fs.readFileSync(path + fileName, 'utf-8');
        // console.log(data);
        var fa = data.toString().split('\n');
        if (fa[fa.length - 1] === '') {
            fa.pop();
        }
        keywordMap[fileName] = [];
        // console.log(keywordMap);
        fa.forEach(function(keyword) {
            if (keyword !== '') {
                keywordMap[fileName].push(keyword);
                // console.log(keyword);
            }
        });
        console.log('loading file name', fileName);
    })
    // console.log(keywordMap);
    return keywordMap;
}

function main() {
    // console.log('-----------------------------------------------------main');
    // getToken(function(AuthToken) {
    // console.log('-----------------------------------------------------getToken')
    var keywordMap = getKeywordMap(path);
    logTime('main ' + timeNow);
    // console.log(keywordMap);
    // logTime('main ' + timeNow);
    var str = fs.readFileSync('../soapXML/googleTrafficEstimate.xml').toString();
    var xml = ET.XML(str);
    getGoogleData(xml, keywordMap);
    // xml.find('.//v201:authToken').text = AuthToken;
    // console.log(xml.find('.//v201:authToken').text);
    // console.log(ET.XML(str))
    // console.log(toXMLString.call(ET.XML(str)));
    // console.log(createXML);
    // dbQuery(xml, createXML);

    // });
    // db.close();
}

function toXMLString() {
    return ET.tostring(this, {
        xml_declaration: false
    });
}

function logTime(str) {
    console.log('----------------------------------------------------- ' + str + '   ', (new Date().getTime() - timeNow.getTime()) / 1000 + 'S');
}
main();
